package com.atguigu.gulimall.member.service.impl;

import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.common.utils.R;
import com.atguigu.common.vo.SocialVO;
import com.atguigu.gulimall.member.config.MemberConfig;
import com.atguigu.gulimall.member.entity.MemberLevelEntity;
import com.atguigu.gulimall.member.exception.UsernameOrPhoneExistException;
import com.atguigu.gulimall.member.service.MemberLevelService;
import com.atguigu.gulimall.member.vo.MemberLoginVo;
import com.atguigu.gulimall.member.vo.RegisterMemberVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.member.dao.MemberDao;
import com.atguigu.gulimall.member.entity.MemberEntity;
import com.atguigu.gulimall.member.service.MemberService;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

@Slf4j
@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Autowired
    MemberLevelService memberLevelService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 会员注册
     * @param registerMemberVo
     */
    @Override
    public void registerMember(RegisterMemberVo registerMemberVo) throws RuntimeException{
        MemberEntity memberEntity = MemberEntity.builder().build();

        //获取会员等级
        MemberLevelEntity memberLevelEntity = memberLevelService.getDefaultMemberLevel();
        memberEntity.setLevelId(memberLevelEntity != null ? memberLevelEntity.getId() : 0L);

        //校验用户或手机号是否已经存在
        checkUsernameAndPhoneExist(registerMemberVo.getUsername(), registerMemberVo.getPhone());

        memberEntity.setUsername(registerMemberVo.getUsername());
        memberEntity.setMobile(registerMemberVo.getPhone());

        //使用spring加密方式将密码进行加密进行存储
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encode = encoder.encode(registerMemberVo.getPassword());
        memberEntity.setPassword(encode);

        String nickName = phoneToNikName(registerMemberVo.getPhone());
        memberEntity.setNickname(nickName);
        memberEntity.setIntegration(0);
        memberEntity.setGrowth(0);
        save(memberEntity);
    }

    /**
     * 用户登录
     * @param memberLoginVo 数据Vo
     * @return memberEntity
     */
    @Override
    public MemberEntity login(MemberLoginVo memberLoginVo) {
        String account = memberLoginVo.getAccount();
        MemberEntity memberEntity = getMemberByAccount(account);
        if (memberEntity == null) {
            return null;
        }

        //校验密码
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        //rawPassword 明文密码 encodePassword 密文密码
        boolean matches = encoder.matches(memberLoginVo.getPassword(), memberEntity.getPassword());
        if (!matches) {
            return null;
        }

        return memberEntity;
    }

    /**
     * 微博社交登录
     * @param socialVO token信息
     * @return r
     */
    @Override
    public R socialLogin(SocialVO socialVO) {
        try {
            log.info("MemberServiceImpl.socialLogin socialLogin register member req params: {}", JSONObject.toJSONString(socialVO));
            //如果该用户登录过，再次登录修改token信息即可
            MemberEntity memberEntity = getMemberByUid(socialVO.getUid());
            if (memberEntity != null) {
                MemberEntity updateMember = MemberEntity.builder()
                        .id(memberEntity.getId())
                        .accessToken(socialVO.getAccessToken())
                        .expiresIn(socialVO.getExpiresIn())
                        .build();
                boolean b = updateById(updateMember);
                Assert.isTrue(b, "社交登录会员信息登录失败");
                memberEntity.setAccessToken(socialVO.getAccessToken());
                memberEntity.setExpiresIn(socialVO.getExpiresIn());
                return R.ok(memberEntity);
            }

            //https://api.weibo.com/2/users/show.json
            HttpResponse httpResponse = null;
            try {
                String userInfoUrl = getUserInfoUrl(socialVO.getAccessToken(), socialVO.getUid());
                httpResponse = HttpRequest.get(userInfoUrl)
                        .timeout(5000)
                        .execute();
            } catch (Exception e) {
                e.printStackTrace();
            }

            //用户没有登录，调用weibo获取用户基本信息插入即可
            memberEntity = MemberEntity.builder().build();
            if (httpResponse.getStatus() == 200) {
                JSONObject jsonObject = JSONObject.parseObject(httpResponse.body());
                //用户昵称
                String screenName = jsonObject.getString("screen_name");
                String gender = jsonObject.getString("gender");
                String profileImageUrl = jsonObject.getString("profile_image_url");
                memberEntity.setNickname(screenName);
                memberEntity.setGender("m".equals(gender) ? 1 : 0);
                memberEntity.setHeader(profileImageUrl);
            }
            MemberLevelEntity memberLevel = memberLevelService.getDefaultMemberLevel();
            memberEntity.setLevelId(memberLevel != null ? memberLevel.getId() : 0L);
            memberEntity.setAccessToken(socialVO.getAccessToken());
            memberEntity.setExpiresIn(socialVO.getExpiresIn());
            memberEntity.setUid(socialVO.getUid());
            boolean b = save(memberEntity);
            Assert.isTrue(b, "社交登录用户会员保存失败");
            return R.ok(memberEntity);
        } catch (HttpException e) {
            log.error("MemberServiceImpl.socialLogin register exception : req params: {}, error: {}", JSONObject.toJSONString(socialVO), e);
            return R.error();
        }
    }

    private String getUserInfoUrl(String accessToken, String uid) {
        return MemberConfig.getUserInfoUrl + "?access_token=" + accessToken + "&uid=" + uid;
    }

    private MemberEntity getMemberByUid(String uid) {
        return getOne(new LambdaQueryWrapper<MemberEntity>()
                        .eq(MemberEntity::getUid, uid));
    }

    /**
     * 根据用户名查询该用户
     * @param account 用户名 或 手机号
     * @return memberEntity
     */
    private MemberEntity getMemberByAccount(String account) {
        MemberEntity memberEntity = getOne(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getUsername, account).or().eq(MemberEntity::getMobile, account));
        return memberEntity;
    }

    /**
     * 手机号中间四位转为*号
     * @param phone 手机号
     * @return string
     */
    private String phoneToNikName(String phone) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < phone.length(); i ++) {
            if (i >= 3 &&  i < 7) {
                builder.append("*");
            }else {
                builder.append(phone.charAt(i));
            }
        }
        return builder.toString();
    }

    /**
     * 校验用户名是否处在，需要保证用户名的唯一性
     * @param username 用户名
     */
    public void checkUsernameAndPhoneExist(String username, String phone) throws UsernameOrPhoneExistException {
        MemberEntity memberEntity = getOne(new LambdaQueryWrapper<MemberEntity>().eq(MemberEntity::getUsername, username).or().eq(MemberEntity::getMobile, phone));
        if (memberEntity != null) {
            throw new UsernameOrPhoneExistException(StringUtils.isEmpty(memberEntity.getUsername()) ? (StringUtils.isEmpty(memberEntity.getMobile()) ? "手机号不存在" : "手机号已经存在") : "用户名已经存在");
        }
    }

}